import 'dart:async';
import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:flutter_learning/isolate/utils/ly_log.dart';
import 'package:flutter_learning/main.dart';
import 'package:flutter_learning/widgets/ly_index_list_view.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:shared_preferences/shared_preferences.dart';

class LYBLEManager {
  LYBLEManager._internal();
  static final LYBLEManager _instance = LYBLEManager._internal();
  static LYBLEManager get share {
    return _instance;
  }

  BluetoothDevice? currentDevice;
  StreamSubscription<BluetoothConnectionState>? currentSubscription;
  List<ScanResult> devices = [];

  void init(Function(List<ScanResult>) callBack) {
    final subscription = FlutterBluePlus.adapterState.listen((BluetoothAdapterState state) {
      LYLog.d("state=$state");
    });
    FlutterBluePlus.onScanResults.listen(
      (results) {
        for (final d in results) {
          LYLog.d("results=$d");
          if (!devices.contains(d)) {
            if (d.advertisementData.advName.contains('Polar')) {
              devices.add(d);
            }
          }
        }
        callBack.call(devices);
      },
      onError: (e) => debugPrint(e),
    );
  }

  Future<bool> requestBluetoothPermissions() async {
    if (await FlutterBluePlus.isSupported == false) {
      return false;
    }

    final status = await Permission.bluetooth.request();
    LYLog.d(status);
    return status == PermissionStatus.granted;
  }

  void scanBlueDevice() async {
    // final res = await requestBluetoothPermissions();
    // if (!res) {
    //   return;
    // }

    LYLog.d("scanBlueDevice");
// listen to scan results
// Note: `onScanResults` clears the results between scans. You should use
//  `scanResults` if you want the current scan results *or* the results from the previous scan.

// Start scanning w/ timeout
// Optional: use `stopScan()` as an alternative to timeout
    await FlutterBluePlus.startScan(
        timeout: const Duration(seconds: 5), continuousUpdates: false, continuousDivisor: 1);

// wait for scanning to stop
//     await FlutterBluePlus.isScanning.where((val) => val == false).first;
  }

  void connectDevice(ScanResult result) async {
    LYLog.d("-------connectDevice--------");
    // listen for disconnection
    final subscription =
        result.device.connectionState.listen((BluetoothConnectionState state) async {
      if (state == BluetoothConnectionState.connected) {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        prefs.setString("remoteId", result.device.remoteId.toString());
//         var device = BluetoothDevice.fromId(remoteId);
// // AutoConnect is convenient because it does not "time out"
// // even if the device is not available / turned off.
//         await device.connect(autoConnect: true);
      }
      // 1. typically, start a periodic timer that tries to
      //    reconnect, or just call connect() again right now
      // 2. you must always re-discover services after disconnection!
      // print("${device.disconnectReason?.code} ${device.disconnectReason?.description}");
    });

    currentSubscription = subscription;

// cleanup: cancel subscription when disconnected
//   - [delayed] This option is only meant for `connectionState` subscriptions.
//     When `true`, we cancel after a small delay. This ensures the `connectionState`
//     listener receives the `disconnected` event.
//   - [next] if true, the the stream will be canceled only on the *next* disconnection,
//     not the current disconnection. This is useful if you setup your subscriptions
//     before you connect.
    result.device.cancelWhenDisconnected(subscription, delayed: true, next: true);

// Connect to the device
    await result.device.connect();
    // final manufacturerData = result.advertisementData.manufacturerData[107];
    // if (manufacturerData != null) {
    //   LYLog.d("manufacturerData=${utf8.decode(manufacturerData)}");
    // }
    List<BluetoothService> services = await result.device.discoverServices();
    LYLog.d("services=$services");
    // for (final service in services) {
    //   for (final characteristic in service.characteristics) {
    //
    //   }
    // }

    BluetoothService? readCharacteristicService = services
        .firstWhereOrNull((service) => service.serviceUuid.toString().toLowerCase() == "180a");
    if (readCharacteristicService != null) {
      BluetoothCharacteristic? readCharacteristic = readCharacteristicService.characteristics
          .firstWhereOrNull((char) => char.characteristicUuid.toString().toLowerCase() == "2a25");
      final value = await readCharacteristic?.read();
      if (value != null) {
        String macStr = utf8.decode(value);
        LYLog.d("macStr=$macStr");
      }
    }

    // 假设已获取设备的服务列表（services 即日志中的 BluetoothService 数组）
    BluetoothService? heartRateService = services
        .firstWhereOrNull((service) => service.serviceUuid.toString().toLowerCase() == "180d");

    if (heartRateService != null) {
      // 从心率服务中找到测量特征（2a37）
      BluetoothCharacteristic? heartRateCharacteristic = heartRateService.characteristics
          .firstWhereOrNull((char) => char.characteristicUuid.toString().toLowerCase() == "2a37");

      if (heartRateCharacteristic != null) {
        // 调用订阅方法
        await subscribeToHeartRate(heartRateCharacteristic);
      } else {
        print("未找到心率测量特征（2a37）");
      }
    } else {
      print("未找到心率服务（180d）");
    }
    // for (BluetoothService service in services) {
    //   //读取服务
    //   for (BluetoothCharacteristic characteristic in service.characteristics) {
    //     // final subscription = characteristic.onValueReceived.listen((data) {
    //     //   final str = String.fromCharCodes(data);
    //     //   LYLog.d("str=$str data=$data");
    //     // });
    //     // result.device.cancelWhenDisconnected(subscription);
    //     // characteristic.setNotifyValue(true);
    //     if (service.serviceUuid.toString().toLowerCase() == '180a'.toLowerCase() &&
    //         characteristic.characteristicUuid.toString().toLowerCase() == '2a25'.toLowerCase()) {
    //       //设备信息服务-设备序列号
    //       List<int> value = await characteristic.read();
    //       String macStr = utf8.decode(value);
    //       LYLog.d(macStr);
    //     }
    //   }
    // }
  }

  Future<void> subscribeToHeartRate(BluetoothCharacteristic characteristic) async {
    try {
      // 1. 启用通知（需先确保设备已连接）
      await characteristic.setNotifyValue(true);
      print("心率数据订阅成功，等待数据...");

      // 2. 监听实时数据
      characteristic.onValueReceived.listen((value) {
        if (value.isNotEmpty) {
          // 解析心率数据（关键：需根据蓝牙心率协议解析二进制数据）
          int heartRate = parseHeartRateValue(value);
          print("$value 当前心率：$heartRate BPM");
        }
      });
    } catch (e) {
      print("订阅失败：$e");
    }
  }

  int parseHeartRateValue(List<int> value) {
    if (value.isEmpty) return 0;

    // 标志位（第1字节）
    int flags = value[0];

    // 判断心率值是8位还是16位（标志位第0位：0=8位，1=16位）
    bool is16Bit = (flags & 0x01) != 0;

    if (is16Bit) {
      // 16位数据：取第2、3字节（小端模式）
      return (value[2] << 8) | value[1];
    } else {
      // 8位数据：取第2字节
      return value[1];
    }
  }

  void autoConnect() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    final remoteId = prefs.getString("remoteId");
    if (remoteId != null && remoteId.isNotEmpty) {
      currentDevice = BluetoothDevice.fromId(remoteId);
      // AutoConnect is convenient because it does not "time out"
      // even if the device is not available / turned off.
      await currentDevice?.connect(autoConnect: true);
      await currentDevice?.connectionState
          .where((val) => val == BluetoothConnectionState.connected)
          .first;
    }
  }

  void dispose() async {
    // Disconnect from device
    await currentDevice?.disconnect();
// cancel to prevent duplicate listeners
    currentSubscription?.cancel();
  }
}
